using System;
using System.Collections.Generic;
using System.Text;
using CookComputing.XmlRpc;

namespace BlogExchange
{
    public static class MetaBlogAPIFactory
    {
        public static IBlogger Create(string url)
        {
            return (IBlogger)
                XmlRpcProxyGen.Create(typeof(IBlogger), url);
        }
    }

    [XmlRpcUrl("http://weblogs.asp.net/blogs/metablog.ashx")]
    public interface IBlogger
    {
        /// <summary>
        /// Deletes a post.
        /// </summary>
        /// <param name="appKey">The app key.</param>
        /// <param name="postid">The postid.</param>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        /// <param name="publish">Where applicable, this specifies whether the blog should be republished after the post has been deleted.</param>
        /// <returns>Always returns true.</returns>
        [XmlRpcMethod("blogger.deletePost")]
        bool deletePost(string appKey, string postid, string username, string password, bool publish);

        /// <summary>
        /// Returns information on all the blogs a given user is a member.
        /// </summary>
        /// <param name="appKey">The app key.</param>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        /// <returns></returns>
        [XmlRpcMethod("blogger.getUsersBlogs")]
        BlogInfo[] getUsersBlogs(string appKey, string username, string password);

        /// <summary>
        /// Updates and existing post to a designated blog using the metaWeblog API. Returns true if completed.
        /// </summary>
        /// <param name="and"></param>
        /// <returns></returns>
        [XmlRpcMethod("metaWeblog.editPost")]
        bool editPost(string postid, string username, string password, Post post, bool publish);

        /// <summary>
        /// Retrieves a list of valid categories for a post using the metaWeblog API. Returns the metaWeblog categories struct collection.
        /// </summary>
        /// <param name="blogid">The blogid.</param>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        /// <returns>Array of struct CategoryInfo</returns>
        [XmlRpcMethod("metaWeblog.getCategories")]
        CategoryInfo[] getCategories(string blogid, string username, string password);

        /// <summary>
        /// Retrieves an existing post using the metaWeblog API. Returns the metaWeblog struct
        /// </summary>
        /// <param name="postid">The postid.</param>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        /// <returns>Post struct</returns>
        [XmlRpcMethod("metaWeblog.getPost")]
        Post getPost(string postid, string username, string password);

        /// <summary>
        /// Retrieves a list of the most recent existing post using the metaWeblog API. Returns the metaWeblog struct collection.
        /// </summary>
        /// <param name="blogid">The blogid.</param>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        /// <param name="numberOfPosts">The number of posts.</param>
        /// <returns>Array of Post instances</returns>
        [XmlRpcMethod("metaWeblog.getRecentPosts")]
        Post[] getRecentPosts(string blogid, string username, string password, int numberOfPosts);

        /// <summary>
        /// Makes a new post to a designated blog using the metaWeblog API. Returns postid as a string.
        /// </summary>
        /// <param name="blogid">The blogid.</param>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        /// <param name="post">The post.</param>
        /// <param name="publish">if set to <c>true</c> [publish].</param>
        /// <returns>String as Post ID</returns>
        [XmlRpcMethod("metaWeblog.newPost")]
        string newPost(string blogid, string username, string password, Post post, Boolean publish);
    }

    public struct BlogInfo
    {
        string blogid;
        string url;
        string blogName;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:BlogInfo"/> class.
        /// </summary>
        /// <param name="blogid">The blogid.</param>
        /// <param name="url">The URL.</param>
        /// <param name="blogName">Name of the blog.</param>
        public BlogInfo(string blogid, string url, string blogName)
        {
            this.blogid = blogid;
            this.url = url;
            this.blogName = blogName;
        }
    }

    public struct Post
    {
        /// <summary>
        /// Required when posting.
        /// </summary>
        public DateTime dateCreated;
        /// <summary>
        /// Required when posting.
        /// </summary>
        public string description;
        /// <summary>
        /// Required when posting.
        /// </summary>
        public string title;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string[] categories;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public Enclosure enclosure;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string link;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string permalink;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public object postid;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public Source source;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string userid;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Post"/> class.
        /// </summary>
        /// <param name="dateCreated">The date created.</param>
        /// <param name="description">The description.</param>
        /// <param name="title">The title.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="enclosure">The enclosure.</param>
        /// <param name="link">The link.</param>
        /// <param name="permalink">The permalink.</param>
        /// <param name="postid">The postid.</param>
        /// <param name="source">The source.</param>
        /// <param name="userid">The userid.</param>
        public Post(DateTime dateCreated, string description, string title,
            string[] categories, Enclosure enclosure, string link,
            string permalink, object postid, Source source, string userid)
        {
            this.dateCreated = dateCreated;
            this.description = description;
            this.title = title;
            this.categories = categories;
            this.enclosure = enclosure;
            this.link = link;
            this.permalink = permalink;
            this.postid = postid;
            this.source = source;
            this.userid = userid;
        }
    }

    public struct CategoryInfo
    {
        public string description;
        public string htmlUrl;
        public string rssUrl;
        public string title;
        public string categoryid;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:CategoryInfo"/> class.
        /// </summary>
        /// <param name="description">The description.</param>
        /// <param name="htmlUrl">The HTML URL.</param>
        /// <param name="rssUrl">The RSS URL.</param>
        /// <param name="title">The title.</param>
        /// <param name="categoryid">The categoryid.</param>
        public CategoryInfo(string description, string htmlUrl, string rssUrl, string title, string categoryid)
        {
            this.description = description;
            this.htmlUrl = htmlUrl;
            this.rssUrl = rssUrl;
            this.title = title;
            this.categoryid = categoryid;
        }
    }

    public struct Enclosure
    {
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public int length;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string type;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string url;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Enclosure"/> class.
        /// </summary>
        /// <param name="length">The length.</param>
        /// <param name="type">The type.</param>
        /// <param name="url">The URL.</param>
        public Enclosure(int length, string type, string url)
        {
            this.length = length;
            this.type = type;
            this.url = url;
        }
    }

    public struct Source
    {
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string name;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string url;
        /// <summary>
        /// Optional
        /// </summary>
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public string type;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Source"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="url">The URL.</param>
        public Source(string name, string url)
        {
            this.name = name;
            this.url = url;
            this.type = "";
        }
    }
}